package com.ehotting.edsta.common.log.aspect;

import com.alibaba.fastjson.JSON;
import com.ehotting.eaf.core.snow.SnowflakeUtil;
import com.ehotting.edsta.common.log.annotation.WebLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.MDC;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * web日志切面类
 *
 * @author 0096001664
 * @since 1.0, 2019-01-16
 */
@Aspect
@Component
@Slf4j
public class WebLogAspect {

    public final static String TRACE_ID = "TRACE_ID";

    @Pointcut("within(@org.springframework.web.bind.annotation.RestController *)")
    public void pointcut() {

    }

    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        MDC.put(TRACE_ID, SnowflakeUtil.nextId64());
        try{
            MethodSignature methodSign = (MethodSignature) joinPoint.getSignature();
            Method method = methodSign.getMethod();
            WebLog logAnno = AnnotationUtils.getAnnotation(method, WebLog.class);
            if (logAnno != null && logAnno.ignore()) {
                return joinPoint.proceed();
            }

            long beginTime = System.currentTimeMillis();
            ServletRequestAttributes requestAttr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
            String ip = requestAttr.getRequest().getRemoteAddr();
            String uri = requestAttr.getRequest().getRequestURI();
            String argsStr = Arrays.toString(joinPoint.getArgs());
            if (argsStr.length()>1024){
                argsStr = argsStr.substring(1024)+"...";
            }
            log.info("Begin===> 请求ip：{}, URI: {}, 请求方法：{}, 请求参数: {}",
                    ip, uri,
                    joinPoint.getSignature().toShortString(),
                    argsStr);

            Object object = joinPoint.proceed();

            if (logAnno != null && logAnno.logReturn()) {
                log.info("End===> 请求ip：{}, URI: {}, 请求方法：{}, 请求参数: {}, 返回参数: {}, 耗时(ms): {}",
                        ip, uri,
                        joinPoint.getSignature().getName(),
                        argsStr,
                        JSON.toJSONString(object),
                        System.currentTimeMillis() - beginTime);
            } else {
                log.info("End===> 请求ip：{}, URI: {}, 请求方法：{}, 请求参数: {}, 耗时(ms): {}"/* + ", 响应参数：{}"*/,
                        ip, uri,
                        joinPoint.getSignature().getName(),
                        argsStr,
                        System.currentTimeMillis() - beginTime);
            }
            return object;
        }catch (Exception e){
            throw e;
        }finally {
            MDC.clear();
        }

    }

}